package com.glink.gateway.common;

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.util.encoders.Hex;

import java.math.BigInteger;

/**
 * 国密SM2加密算法
 * 加密方式 sm2p256v1
 * 加密模式共有两种(C1C2C3 和  C1C3C2)，本算法暂时支持 C1C2C3
 *
 * @author rcl026@163.com
 * @date 2023/2/6
 * @since 1.8.4.RELEASE
 */
public class Sm2EncryptionUtil {
    private static final String SM_2_P_256_V_1 = "sm2p256v1";

    /**
     * SM2解密算法
     *
     * @param priKeyHexString 私钥（16进制字符串）
     * @param cipherData      密文数据
     * @return
     */
    public static String decrypt(String priKeyHexString, String cipherData) {

        // 使用BC库加解密时密文以04开头，传入的密文前面没有04则补上
        if (!cipherData.startsWith("04")) {
            cipherData = "04" + cipherData;
        }
        byte[] cipherDataByte = Hex.decode(cipherData);

        //获取一条SM2曲线参数
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName(SM_2_P_256_V_1);
        //构造domain参数
        ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());

        BigInteger privateKeyD = new BigInteger(priKeyHexString, 16);
        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters);

        SM2Engine sm2Engine = new SM2Engine();
        // 设置sm2为解密模式
        sm2Engine.init(false, privateKeyParameters);

        String result = "";
        try {
            byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
            return new String(arrayOfBytes);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("SM2解密时出现异常:" + e.getMessage());
        }
        return result;
    }
}
